package sys_serv

import (
	"strconv"
	"strings"
	"ubt-rbac-service/internal/app/model"
	"ubt-rbac-service/internal/app/model/sys_mod"
	"ubt-rbac-service/internal/app/util"
)

type sysFile struct{}

var SysFileServ = sysFile{}

// Add 新增文件
func (s *sysFile) Add(req *sys_mod.SysFileAddReq) *model.Result {
	sqlStr := "INSERT INTO sys_file(file_id, file_name, file_size, kind, file_ext, real_path, visit_url, add_time, opt_org) " +
		"VALUES ($1, $2, $3, $4, $5, $6, $7, EXTRACT(EPOCH FROM NOW()), $8)"
	retCode, retMsg := util.CudData(sqlStr, req.FileId, req.FileName, req.FileSize, req.Kind, req.FileExt, req.RealPath, req.VisitUrl, req.OptOrg)
	return &model.Result{RetCode: retCode, RetMsg: retMsg}
}

// UpdName 修改文件名称
func (s *sysFile) UpdName(req *sys_mod.SysFileNameReq) *model.Result {
	sqlStr := "UPDATE sys_file SET file_name=$1, upd_time=EXTRACT(EPOCH FROM NOW()) WHERE file_id=$2"
	retCode, retMsg := util.CudData(sqlStr, req.FileName, req.FileId)
	return &model.Result{RetCode: retCode, RetMsg: retMsg}
}

// UpdType 修改文件类型
func (s *sysFile) UpdType(req *sys_mod.SysFileTypeReq) *model.Result {
	var (
		param []interface{}
		q     string
		n     = 1
	)
	param = append(param, req.FileType)
	idList := strings.Split(req.FileIds, ",")
	for _, curId := range idList {
		n++
		q += "$" + strconv.Itoa(n) + ","
		param = append(param, curId)
	}
	q = q[:len(q)-1]
	sqlStr := "UPDATE sys_file SET file_type=$1, upd_time=EXTRACT(EPOCH FROM NOW()) WHERE file_id IN (" + q + ")"
	retCode, retMsg := util.CudData(sqlStr, param...)
	return &model.Result{RetCode: retCode, RetMsg: retMsg}
}

// Delete 删除文件
func (s *sysFile) Delete(fileId string) *model.Result {
	sqlStr := "SELECT kind, real_path FROM sys_file WHERE file_id=$1"
	if dbMap, err := util.GetOne(sqlStr, fileId); err == nil && len(dbMap) > 0 {
		util.ImgProc.RemoveFile(dbMap["kind"].(int64), dbMap["realPath"].(string))
	}
	sqlStr = "DELETE FROM sys_file WHERE file_id=$1"
	retCode, retMsg := util.CudData(sqlStr, fileId)
	return &model.Result{RetCode: retCode, RetMsg: retMsg}
}

// Deletes 批量删除文件
func (s *sysFile) Deletes(fileIds string) *model.Result {
	var (
		param []interface{}
		q     string
		n     = 0
	)
	idList := strings.Split(fileIds, ",")
	for _, curId := range idList {
		n++
		q += "$" + strconv.Itoa(n) + ","
		param = append(param, curId)
	}
	q = q[:len(q)-1]
	sqlStr := "SELECT kind, real_path FROM sys_file WHERE file_id IN (" + q + ")"
	if dbMap, err := util.GetAll(sqlStr, param...); err == nil && len(dbMap) > 0 {
		for _, path := range dbMap {
			util.ImgProc.RemoveFile(path["kind"].(int64), path["realPath"].(string))
		}
	}
	sqlStr = "DELETE FROM sys_file WHERE file_id IN (" + q + ")"
	retCode, retMsg := util.CudData(sqlStr, param...)
	return &model.Result{RetCode: retCode, RetMsg: retMsg}
}

// One 获取文件详情
func (s *sysFile) One(fileId string) *model.Result {
	sqlStr := "SELECT a.file_id, a.file_name, a.file_size, a.kind, a.file_ext, a.file_type, b.type_name, b.type_code, " +
		"a.visit_url, a.add_time " +
		"FROM sys_file a " +
		"LEFT JOIN sys_type b ON a.file_type=b.type_id " +
		"WHERE a.file_id=$1"
	if dbMap, err := util.GetOne(sqlStr, fileId); err == nil && len(dbMap) > 0 {
		return &model.Result{RetCode: 1001, RetMsg: "ok", RetData: dbMap}
	} else {
		return &model.Result{RetCode: 1000, RetMsg: "暂无内容"}
	}
}

// Count 获取文件数量
func (s *sysFile) Count(req *sys_mod.SysFilePageReq) *model.Result {
	sqlStr := "SELECT COUNT(1) AS nums FROM sys_file WHERE opt_org=$1"
	var param []interface{}
	param = append(param, req.OptOrg)
	var n = 1
	if req.SchName != "" {
		sqlStr += " AND ("
		nameArr := strings.Split(req.SchName, " ")
		for _, name := range nameArr {
			sqlStr += "file_name LIKE '%'||$" + strconv.Itoa(n+1) + "||'%' OR " +
				"file_ext LIKE '%'||$" + strconv.Itoa(n+2) + "||'%' OR "
			param = append(param, name)
			param = append(param, name)
			n += 2
		}
		sqlStr = sqlStr[:len(sqlStr)-4]
		sqlStr += ")"
	}
	if req.Kind > 0 {
		n++
		sqlStr += " AND kind=$" + strconv.Itoa(n)
		param = append(param, req.Kind)
	}
	if req.FileType != "" {
		n++
		sqlStr += " AND file_type=$" + strconv.Itoa(n)
		param = append(param, req.FileType)
	}
	if req.BeginTime > 0 {
		n++
		sqlStr += " AND add_time>=$" + strconv.Itoa(n)
		param = append(param, req.BeginTime)
	}
	if req.EndTime > 0 {
		n++
		sqlStr += " AND add_time<=$" + strconv.Itoa(n)
		param = append(param, req.EndTime)
	}
	if dbMap, err := util.GetOne(sqlStr, param...); err == nil {
		return &model.Result{RetCode: 1001, RetMsg: "ok", RetData: dbMap["nums"]}
	} else {
		return &model.Result{RetCode: 1000, RetMsg: "暂无内容"}
	}
}

// Page 获取文件分页列表
func (s *sysFile) Page(req *sys_mod.SysFilePageReq) *model.Result {
	sqlStr := "SELECT a.file_id, a.file_name, a.file_ext, a.kind, b.type_name, b.type_code, a.visit_url, a.add_time " +
		"FROM sys_file a LEFT JOIN sys_type b ON a.file_type=b.type_id WHERE a.opt_org=$1"
	var param []interface{}
	param = append(param, req.OptOrg)
	var n = 1
	if req.SchName != "" {
		sqlStr += " AND ("
		nameArr := strings.Split(req.SchName, " ")
		for _, name := range nameArr {
			sqlStr += "a.file_name LIKE '%'||$" + strconv.Itoa(n+1) + "||'%' OR " +
				"a.file_ext LIKE '%'||$" + strconv.Itoa(n+2) + "||'%' OR "
			param = append(param, name)
			param = append(param, name)
			n += 2
		}
		sqlStr = sqlStr[:len(sqlStr)-4]
		sqlStr += ")"
	}
	if req.Kind > 0 {
		n++
		sqlStr += " AND a.kind=$" + strconv.Itoa(n)
		param = append(param, req.Kind)
	}
	if req.FileType != "" {
		n++
		sqlStr += " AND a.file_type=$" + strconv.Itoa(n)
		param = append(param, req.FileType)
	}
	if req.BeginTime > 0 {
		n++
		sqlStr += " AND a.add_time>=$" + strconv.Itoa(n)
		param = append(param, req.BeginTime)
	}
	if req.EndTime > 0 {
		n++
		sqlStr += " AND a.add_time<=$" + strconv.Itoa(n)
		param = append(param, req.EndTime)
	}
	sqlStr += " ORDER BY a.add_time DESC LIMIT $" + strconv.Itoa(n+1) + " OFFSET $" + strconv.Itoa(n+2)
	param = append(param, req.Limit)
	param = append(param, req.Offset)
	if dbMap, err := util.GetAll(sqlStr, param...); err == nil {
		return &model.Result{RetCode: 1001, RetMsg: "ok", RetData: dbMap}
	} else {
		return &model.Result{RetCode: 1000, RetMsg: "暂无内容"}
	}
}

// GetRealPath 获取文件物理路径
func (s *sysFile) GetRealPath(fileId string) (string, string) {
	sqlStr := "SELECT real_path, file_name||file_ext file_name FROM sys_file WHERE file_id=$1"
	if dbMap, err := util.GetOne(sqlStr, fileId); err == nil {
		return dbMap["realPath"].(string), dbMap["fileName"].(string)
	} else {
		return "", ""
	}
}
